using System;
using System.Collections.Generic;
using System.Linq;
using FreeSql;
using LF.Domain.Entities;
using LF.Domain.Helper;

namespace LF.Domain.Services.Impl
{
    /// <summary>
    /// 权限数据库操作服务，负责权限数据的增删改查
    /// </summary>
    public class PermissionDbService : IPermissionDbService
    {
        private readonly IFreeSql _freeSql;

        public PermissionDbService()
        {
            _freeSql = FreeSqlHelper.DbContext;
        }

        /// <summary>
        /// 根据扫描到的权限更新数据库
        /// 1. 添加新权限（数据库中不存在的）
        /// 2. 更新权限名称（已存在且未删除的权限）
        /// 3. 恢复逻辑删除的权限（扫描到系统有但数据库中逻辑删除的）
        /// 4. 逻辑删除不再存在的权限（数据库有但扫描结果中没有的）
        /// </summary>
        public void SavePermissionsToDatabase(List<Permission> scannedPermissions)
        {
            // 获取数据库中已有的权限（包括逻辑删除的）
            var existingPermissions = _freeSql.Queryable<Permission>()
                .ToList();

            // 需要添加的权限（数据库中完全不存在的）
            var permissionsToAdd = scannedPermissions
                .Where(p => !existingPermissions.Any(ep => ep.Code == p.Code))
                .ToList();

            // 需要更新的权限（存在且未删除，但名称有变化）
            var permissionsToUpdate = scannedPermissions
                .Where(p => existingPermissions.Any(ep => ep.Code == p.Code && !ep.IsDelete && ep.Name != p.Name))
                .Select(p => 
                {
                    var existing = existingPermissions.First(ep => ep.Code == p.Code && !ep.IsDelete);
                    existing.Name = p.Name;
                    existing.UpdateTime = DateTime.Now;
                    return existing;
                })
                .ToList();

            // 需要恢复的权限（扫描到系统有但数据库中逻辑删除的）
            var permissionsToRestore = scannedPermissions
                .Where(p => existingPermissions.Any(ep => ep.Code == p.Code && ep.IsDelete))
                .Select(p => 
                {
                    var existing = existingPermissions.First(ep => ep.Code == p.Code && ep.IsDelete);
                    existing.Name = p.Name;
                    existing.IsDelete = false;
                    existing.UpdateTime = DateTime.Now;
                    return existing;
                })
                .ToList();

            // 要删除的权限(数据库有但扫描结果中没有的，且未逻辑删除的)
            var permissionsToDelete = existingPermissions
                .Where(ep => !scannedPermissions.Any(p => p.Code == ep.Code) && !ep.IsDelete)
                .ToList();

            // 使用事务进行数据库操作
            _freeSql.Transaction(() =>
            {
                // 添加新权限
                if (permissionsToAdd.Any())
                {
                    _freeSql.Insert(permissionsToAdd).ExecuteAffrows();
                }

                // 更新权限名称
                foreach (var permission in permissionsToUpdate)
                {
                    _freeSql.Update<Permission>()
                        .SetSource(permission)
                        .ExecuteAffrows();
                }

                // 恢复逻辑删除的权限
                foreach (var permission in permissionsToRestore)
                {
                    _freeSql.Update<Permission>()
                        .SetSource(permission)
                        .ExecuteAffrows();
                }

                // 逻辑删除不再存在的权限
                foreach (var permission in permissionsToDelete)
                {
                    permission.IsDelete = true;
                    permission.UpdateTime = DateTime.Now;
                    _freeSql.Update<Permission>()
                        .SetSource(permission)
                        .ExecuteAffrows();
                }
            });
        }

        /// <summary>
        /// 获取所有权限列表
        /// </summary>
        public List<Permission> GetAllPermissions()
        {
            return _freeSql.Queryable<Permission>()
                .Where(p => !p.IsDelete)
                .ToList();
        }

        /// <summary>
        /// 根据编码获取权限
        /// </summary>
        public Permission GetPermissionByCode(string code)
        {
            return _freeSql.Queryable<Permission>()
                .Where(p => p.Code == code && !p.IsDelete)
                .First();
        }
    }
} 